package com.mls.fivedistrict.server.impl;

import com.github.pagehelper.PageHelper;
import com.mls.fivedistrict.common.PageFilter;
import com.mls.fivedistrict.dao.ParadropMapper;
import com.mls.fivedistrict.enums.RecordStatusEnum;
import com.mls.fivedistrict.exception.CustomerException;
import com.mls.fivedistrict.pojo.*;
import com.mls.fivedistrict.server.IntegralService;
import com.mls.fivedistrict.server.ParadropServer;
import com.mls.fivedistrict.server.PropertyService;
import com.mls.fivedistrict.server.RecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import static java.math.BigDecimal.ROUND_DOWN;

/**
 * Created by chenxiuxiang on 2018/4/15.
 */
@Service
public class ParadropServerImpl implements ParadropServer {

    @Autowired
    ParadropMapper paradropMapper;
    @Autowired
    PropertyService propertyService;
    @Autowired
    RecordService recordService;
    @Autowired
    IntegralService integralService;

    @Override
    public int addParadrop(Paradrop paradrop) {
        int i = paradropMapper.insertSelective(paradrop);
        return i;
    }

    @Override
    public int editParadrop(Paradrop property) {
        int i = paradropMapper.updateByPrimaryKeySelective(property);
        return i;
    }

    @Override
    public List<Paradrop> getParadropList(PageFilter pageFilter) {
        ParadropExample paradropExample = new ParadropExample();
        ParadropExample.Criteria criteria = paradropExample.createCriteria();
        criteria.andIsDeleteEqualTo(false);
        PageHelper.startPage(pageFilter.getPageNum(), pageFilter.getPageSize());
        List<Paradrop> paradrops = paradropMapper.selectByExample(paradropExample);
        return paradrops;
    }

    @Override
    public int deleteParadrop(Long id) {
        Paradrop paradrop = paradropMapper.selectByPrimaryKey(id);
        Optional.ofNullable(paradrop).orElseThrow(() -> new CustomerException("空投计划不存在"));
        Paradrop newParadrop = new Paradrop();
        newParadrop.setId(id);
        newParadrop.setIsDelete(true);
        int i = paradropMapper.updateByPrimaryKeySelective(newParadrop);
        return i;
    }

    @Transactional
    @Override
    public int startParadrop(Long id) {
        Paradrop paradrop = paradropMapper.selectByPrimaryKey(id);
        Optional.ofNullable(paradrop).orElseThrow(() -> new CustomerException("空投计划不存在"));
        //获取总量
        BigDecimal total = paradrop.getTotal();
        //获取DWQ总量
        BigDecimal dwqTotal = propertyService.getDwqTotal();
        //每个DWQ分多少
        BigDecimal divide = total.divide(dwqTotal, 8, ROUND_DOWN);
        //计算每个用户分多少插入资产 如果这种积分的资产已经存在 插入 否则更新
        List<ParadropProperty> paradropPropertyList = new ArrayList<>();
        List<Property> dwqProperties = propertyService.getPropertiesByIntegral(18L);
        //总共分多少出去
        BigDecimal divideSumTotal = new BigDecimal(0);
        for (Property property : dwqProperties) {
            ParadropProperty paradropProperty = new ParadropProperty();
            BigDecimal getTotal = property.getTotal().multiply(divide).setScale(8, ROUND_DOWN);
            paradropProperty.setTotal(getTotal.setScale(8, ROUND_DOWN));
            paradropProperty.setSourceTotal(getTotal.setScale(8, ROUND_DOWN));
            paradropProperty.setUserId(property.getUserId());
            paradropProperty.setIntegralId(paradrop.getIntegralId());
            paradropPropertyList.add(paradropProperty);
            divideSumTotal = divideSumTotal.add(getTotal).setScale(8, ROUND_DOWN);

        }
        //判断是插入还是更新
        List<ParadropProperty> insertPropertyList = new ArrayList<>();
        List<ParadropProperty> updatePropertyList = new ArrayList<>();
        //获取目前存在paradrop对应的资产的用户集合
        List<Property> exisProperties = propertyService.getPropertiesByIntegral(paradrop.getIntegralId());
        List<Long> existUserIds = new ArrayList<>();
        if (exisProperties.size() > 0) {
            for (Property p : exisProperties) {
                existUserIds.add(p.getUserId());
            }
        }

        if (existUserIds.size() > 0) {
            for (ParadropProperty paradropProperty : paradropPropertyList) {

                int i = existUserIds.indexOf(paradropProperty.getUserId());
                if (i >= 0) {
                    //代表存在 更新
                    paradropProperty.setPropertyId(exisProperties.get(i).getId());
                    paradropProperty.setTotal(exisProperties.get(i).getTotal().add(paradropProperty.getTotal()).setScale(8, ROUND_DOWN));
                    updatePropertyList.add(paradropProperty);
                } else {
                    //代表不存在 添加
                    insertPropertyList.add(paradropProperty);
                }
            }
        } else {
            insertPropertyList.addAll(paradropPropertyList);
        }

        if (updatePropertyList.size() > 0) {
            //4-1更新
            //每10000条执行一次进行插入
            //总共执行多少次
            int totlaSplice = 10000;
            int times = (int) Math.ceil(updatePropertyList.size() * 1.0 / totlaSplice);
            if (times > 1) {
                for (int i = 0; i < times; i++) {
                    List<ParadropProperty> timeRecords = new ArrayList<>();
                    int sum = updatePropertyList.size();
                    if ((i + 1) * totlaSplice < updatePropertyList.size()) {
                        sum = (i + 1) * totlaSplice;
                    }
                    for (int t = i * totlaSplice; t < sum; t++) {
                        timeRecords.add(updatePropertyList.get(t));
                    }
                    propertyService.updatePropertyBashByParadrop(timeRecords);
                }
            } else {
                propertyService.updatePropertyBashByParadrop(updatePropertyList);
            }
//            propertyService.updatePropertyBashByParadrop(updatePropertyList);
        }
        if (insertPropertyList.size() > 0) {
            //4-2插入
            //每10000条执行一次进行插入
            //总共执行多少次
            int totlaSplice = 10000;
            int times = (int) Math.ceil(insertPropertyList.size() * 1.0 / totlaSplice);
            if (times > 1) {
                for (int i = 0; i < times; i++) {
                    List<ParadropProperty> timeRecords = new ArrayList<>();
                    int sum = insertPropertyList.size();
                    if ((i + 1) * totlaSplice < insertPropertyList.size()) {
                        sum = (i + 1) * totlaSplice;
                    }
                    for (int t = i * totlaSplice; t < sum; t++) {
                        timeRecords.add(insertPropertyList.get(t));
                    }
                    propertyService.addPropertyBashByParadrop(timeRecords);
                }
            } else {
                propertyService.addPropertyBashByParadrop(insertPropertyList);
            }

//            propertyService.addPropertyBashByParadrop(insertPropertyList);
        }
        List<Record> records = new ArrayList<>();
        for (ParadropProperty p : paradropPropertyList) {
            Record record = new Record();
            record.setUserId(p.getUserId());
            record.setSource("空投计划");
            record.setStatus(RecordStatusEnum.ALREADYRECEIVE.getValue());
            record.setValue(p.getSourceTotal());
            record.setIntergralId(p.getIntegralId());
            records.add(record);
        }
        //插入记录（空投计划）根据用户存在的dwq*每个dwq分多少等于用户应该得到的dwq总数
        if (records.size() > 0) {
            int totlaSplice = 10000;
            int times = (int) Math.ceil(records.size() * 1.0 / totlaSplice);
            if (times > 1) {
                for (int i = 0; i < times; i++) {
                    int sum = records.size();
                    if ((i + 1) * totlaSplice < records.size()) {
                        sum = (i + 1) * totlaSplice;
                    }
                    List<Record> timeRecords = new ArrayList<>();
                    for (int t = i * totlaSplice; t < sum; t++) {
                        timeRecords.add(records.get(t));
                    }
                    recordService.insertBash(timeRecords);
                }
            } else {
                recordService.insertBash(records);
            }
//            int i = recordService.insertBash(records);
        }
        //更新积分使用数量
        Integral integralDetail = integralService.getIntegralDetail(paradrop.getIntegralId());
        Integral integral = new Integral();
        integral.setUserIntegral(integralDetail.getUserIntegral().add(divideSumTotal).setScale(8, ROUND_DOWN));
        integral.setId(integralDetail.getId());
        integralService.editIntegral(integral);
        Paradrop newParadrop = new Paradrop();
        newParadrop.setId(id);
        newParadrop.setExecuteTime(paradrop.getExecuteTime() + 1);
        newParadrop.setUpdateTime(new Date());
        newParadrop.setDwqTotal(dwqTotal);
        newParadrop.setUserTotal(dwqProperties.size());
        newParadrop.setDivide(divide);
        int i = paradropMapper.updateByPrimaryKeySelective(newParadrop);
        return i;
    }

    @Override
    public Paradrop getParadropDetail(Long paradropId) {
        Paradrop paradrop = paradropMapper.selectByPrimaryKey(paradropId);
        return paradrop;
    }
}
